/*   Shotscreens
 *   Copyright (C) 2011, Andrew Lisin (http://crystalnix.com)
 *   Copyright (C) 2011, Viatcheslav Gachkaylo <vgachkaylo@gmail.com>
 *
 *   This program is free software: you can redistribute it and/or modify
 *   it under the terms of the GNU General Public License as published by
 *   the Free Software Foundation, either version 3 of the License, or
 *   (at your option) any later version.
 *
 *   This program is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *   GNU General Public License for more details.
 *
 *   You should have received a copy of the GNU General Public License
 *   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#include "fullscreenwidget.h"
#include "ui_menuscreenshot.h"
#include <QApplication>
#include <QPainter>
#include <QPaintEvent>
#include <QDesktopWidget>
#include <QMouseEvent>

FullscreenWidget::FullscreenWidget(const QPixmap& pixmap, QWidget *parent /*=0*/) :
        QWidget(parent), esc(this), holdLeftButton(false), ui(new Ui::menuscreenshot), menu(new QWidget(this))
{
    screenPixmap = fillPixmap = pixmap;
    prepare();
    initializeShortcut();
    ui->setupUi(menu);

    // menu
    menu->hide();
    menu->setAutoFillBackground(true); // it would be cool to use some awesome background for menu! but for now let it be.

    connectButtons();

    this->setAttribute(Qt::WA_TranslucentBackground, true);

    hilighter.setWindowFlags(Qt::FramelessWindowHint);
    hilighter.setAttribute(Qt::WA_ShowWithoutActivating);
    QPalette p(hilighter.palette());
    p.setColor(QPalette::Background, Qt::black);
    hilighter.setPalette(p);
    hilighter.setWindowOpacity(0.3);
}

FullscreenWidget::~FullscreenWidget() {
    qDebug("~FullscreenWidget()");
    delete ui;
}
// initialization of all elements

void FullscreenWidget::prepare()
{
    this->setWindowFlags(Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint);
    this->setAttribute(Qt::WA_DeleteOnClose);
    this->resize(QApplication::desktop()->width(), QApplication::desktop()->height());
    this->move(QApplication::desktop()->x(), QApplication::desktop()->y());
    this->setCursor(Qt::CrossCursor);
    this->setMouseTracking(true);
    this->activateWindow();

    allocating = true;
    switchToFrameSelectMode();

    if (!updateWindowsInfo())
        qWarning("Error: can not initialize visible windows info.");
}

void FullscreenWidget::initializeShortcut()
{
    esc.setKey(Qt::Key_Escape);
    connect(&esc, SIGNAL(activated()), this, SLOT(close()));
}


// events

void FullscreenWidget::paintEvent(QPaintEvent* event)
{
    QPainter painter(this);
    painter.drawPixmap(event->rect(), screenPixmap);
}

void FullscreenWidget::mouseMoveEvent(QMouseEvent* event)
{
    if(allocating) {
        if (!selectingWindow) {
            screenPixmap = originalPixmap;

            if (!holdLeftButton) {
                int idx = getWindowIndexAtPoint(QCursor::pos());
                if (idx != -1 && idx != currentWindowIndex) {
                    QRect tmp = windowsInfo[idx].frame;
                    QPainter painter(&screenPixmap);
                    painter.drawPixmap(tmp, fillPixmap, tmp);
                    firstPoint = tmp.topLeft();
                    secondPoint = tmp.bottomRight();
                    update();

                    currentWindowIndex = idx;
                }
            } else {
                drawCursorLines(event);
                drawPosRect(event);
                //if(holdLeftButton) {
                secondPoint = event->pos();
                QRect tmp = getRectFromPoints();
                QPainter painter(&screenPixmap);

                painter.drawPixmap(tmp, fillPixmap, tmp);
                painter.end();
                //}
                update();
            }
        } else {
            int idx = getWindowIndexAtPoint(QCursor::pos());
            if (idx != -1 && currentWindowIndex != idx) {
                hilightWindowAt(idx);
                currentWindowIndex = idx;
            }
        }
    }
}

void FullscreenWidget::mousePressEvent(QMouseEvent* event)
{
    // left mouse button click
    if(!selectingWindow && (event->button() == Qt::LeftButton) && allocating)
    {
        holdLeftButton = true;
        firstPoint = event->pos();
    }

    // right mouse button click
    if((event->button() == Qt::RightButton) && allocating) // when allocating we stop selecting...
    {
        this->close();
    }
    else if((event->button() == Qt::RightButton) && !allocating) // ...and when allocation has been done we recapture image
    {
        recaptureAction();
    }
}

void FullscreenWidget::mouseReleaseEvent(QMouseEvent* event) {
    if(!selectingWindow && (event->button() == Qt::LeftButton) && (holdLeftButton == true)) { // we test for second condition for user can quick hold left button after capture action
                                                                          // perhaps there is now need in it, but let it be for now.
        holdLeftButton = false;
        secondPoint = event->pos();

        screenPixmap = originalPixmap;
        QPainter painter(&screenPixmap);

        QRect tmp = getRectFromPoints();

        if((tmp.width() < min_appropriate_size) || (tmp.height() < min_appropriate_size)) { // check for minimum appropriate area.
            //drawCursorLines(event);
            //drawPosRect(event);
            //update();
            //return;
            int idx = getWindowIndexAtPoint(firstPoint);
            if (idx == -1)
                return;

            tmp = windowsInfo[idx].frame;

            firstPoint = tmp.topLeft();
            secondPoint = tmp.bottomRight();
        }

        // if size of screenshot is ok:
        painter.drawPixmap(tmp, fillPixmap, tmp);

        allocating = false;
        setCursor(Qt::ArrowCursor);
        showMenu(tmp);
        update();
    } else if (selectingWindow && event->button() == Qt::LeftButton) {
        allocating = false;
        selectingWindow = false;
        setCursor(Qt::ArrowCursor);
        int idx = getWindowIndexAtPoint(QCursor::pos());
        if (idx != -1)
            emit pixmapSended(getQPixmapForWindowIndex(idx));
    }
}

// cursor drawing methods

void FullscreenWidget::drawPosRect(QMouseEvent* event) {
    const int w = 85, h = 20; // Maybe size should adapt to screen resolution? But let it be for now...
    const int desktopWidth = QApplication::desktop()->width();
    const int desktopHeight = QApplication::desktop()->height();
    const int x = event->x(), y = event->y();
    QRect posRect;

    // We should define a position of posRect for must been visible
    if ((y + h > desktopHeight) && (x + w < desktopWidth))
        posRect.setCoords(x, y - h, x + w, y);
    else if ((y + h > desktopHeight) && (x + w > desktopWidth))
        posRect.setCoords(x - w, y - h, x, y);
    else if ((y + h < desktopHeight) && (x + w > desktopWidth))
        posRect.setCoords(x - w, y, x, y + h);
    else
        posRect.setCoords(x, y, x + w, y + h);

    QPainter painter(&screenPixmap);
    painter.setBrush(Qt::darkGray);
    painter.drawRect(posRect);
    painter.drawText(posRect, Qt::AlignCenter, QString(" %1 x %2 ").arg(event->x()).arg(event->y()));
}

void FullscreenWidget::drawCursorLines(QMouseEvent* event) {
    QPainter painter(&screenPixmap);
    painter.drawLine(event->x(), 0, event->x(), QApplication::desktop()->height()); // vertical line
    painter.drawLine(0, event->y(), QApplication::desktop()->width(), event->y()); // horizontal line
}

// other methods

QRect FullscreenWidget::getRectFromPoints() {
    QRect rect;

    if (firstPoint.x() < secondPoint.x()) {
        rect.setX(firstPoint.x() - 1);
        rect.setWidth(secondPoint.x() - firstPoint.x());
    } else {
        rect.setX(secondPoint.x() + 1);
        rect.setWidth(firstPoint.x() - secondPoint.x());
    }

    if (firstPoint.y() < secondPoint.y()) {
        rect.setY(firstPoint.y() - 1);
        rect.setHeight(secondPoint.y() - firstPoint.y());
    } else {
        rect.setY(secondPoint.y() + 1);
        rect.setHeight(firstPoint.y() - secondPoint.y());
    }

    return rect;
}

void FullscreenWidget::showMenu(QRect tmp) {
    int menu_x=0,menu_y=0;

    if((tmp.bottomLeft().x() + menu->width()) > QApplication::desktop()->width()) {
        menu_x = tmp.bottomLeft().x() - menu->width() - 2;
    }
    else {
        menu_x = tmp.bottomLeft().x();
    }

    if(tmp.bottomLeft().y() + menu->height() > QApplication::desktop()->height()) {
        menu_y = tmp.bottomLeft().y() - menu->height() - 2;
    }
    else {
        menu_y = tmp.bottomLeft().y();
    }
    menu->move(menu_x,menu_y);
    menu->show();
    menu->update();
}

// menu actions:

void FullscreenWidget::connectButtons() {
    connect(ui->imageButton, SIGNAL(clicked()), this, SLOT(imageAction()));
    connect(ui->reallocateButton, SIGNAL(clicked()), this, SLOT(recaptureAction()));
    connect(ui->videoButton, SIGNAL(clicked()), this, SLOT(videoAction()));
    connect(ui->escButton, SIGNAL(clicked()), this, SLOT(close()));
}

void FullscreenWidget::recaptureAction() {
     menu->hide();
     screenPixmap = fillPixmap;
     prepare(); // back to beginning
     this->showNormal();
}

void FullscreenWidget::escAction() {
    this->close();
}

void FullscreenWidget::videoAction() {
    // later!
}

void FullscreenWidget::imageAction() {
    QRect imageRect = getRectFromPoints();
    QPixmap tmp(imageRect.size());
    QPainter painter(&tmp);
    painter.drawPixmap(QPoint(0, 0), fillPixmap, imageRect);

    emit pixmapSended(tmp);
}

void FullscreenWidget::keyReleaseEvent(QKeyEvent *event) {
    if (allocating && event->key() == Qt::Key_Space) {
        if (!selectingWindow) {
            int idx = getWindowIndexAtPoint(QCursor::pos());
            if (idx != -1) {
                selectingWindow = true;

                QPainter painter(&screenPixmap);
                painter.setCompositionMode(QPainter::CompositionMode_Source);
                painter.setOpacity(0.05);
                painter.setBrush(Qt::white);
                painter.drawRect(this->rect());
                painter.end();

                update();

                hilighter.show();
                hilightWindowAt(idx);
                this->activateWindow();
                currentWindowIndex = idx;
            }

        } else {
            hilighter.hide();

            switchToFrameSelectMode();
        }
    }
}

void FullscreenWidget::switchToFrameSelectMode() {
    selectingWindow = false;
    currentWindowIndex = -1;
    screenPixmap = fillPixmap;
    QPainter painter(&screenPixmap);
    painter.setOpacity(0.5);
    painter.setBrush(Qt::gray);
    painter.drawRect(this->rect());
    originalPixmap = screenPixmap;
}

#ifndef Q_WS_MAC
bool FullscreenWidget::updateWindowsInfo() {
    return true;
}

int FullscreenWidget::getWindowIndexAtPoint(const QPoint &pt) {
    return -1;
}

void FullscreenWidget::hilightWindowAt(int index) {}

QPixmap getQPixmapForWindowIndex(int index) {}
#endif
